package com.kdd.campus.sh.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageHelper;
import com.kdd.campus.common.util.RedisUtil;
import com.kdd.campus.sh.convert.OrderChangeConvert;
import com.kdd.campus.sh.convert.OrderDetailConvert;
import com.kdd.campus.sh.convert.QueryOrderItemConvert;
import com.kdd.campus.sh.dao.ShOrderItemMapper;
import com.kdd.campus.sh.dao.ShOrderMapper;
import com.kdd.campus.sh.dao.ShProductMapper;
import com.kdd.campus.sh.dto.*;
import com.kdd.campus.sh.po.ShOrder;
import com.kdd.campus.sh.po.ShOrderItem;
import com.kdd.campus.sh.po.ShProduct;
import com.kdd.campus.sh.service.OrderService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @Auther: fcp
 * @Date: 2020/4/29 22:32
 * @Description:
 */
@Service
public class OrderServiceImpl implements OrderService {
    @Value("${redis.key.prefix.orderId}")
    private String REDIS_KEY_PREFIX_ORDER_ID;

    private Logger logger = LoggerFactory.getLogger(OrderServiceImpl.class);

    @Autowired
    private ShOrderMapper orderMapper;

    @Autowired
    private ShOrderItemMapper orderItemMapper;

    @Autowired
    private ShProductMapper productMapper;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Override
    public List<QueryOrderDto> findList(Long userId, Integer pageNum, Integer pageSize, OrderParam orderParam) {
        // 1. 根据条件查询该user的订单

        // 查询待付款订单
        if (orderParam.getNotPayment() != null && orderParam.getNotPayment()){
            return findWaitPayment(userId,pageNum,pageSize,orderParam);
        }

        // 查询待收获（待完成）订单
        if (orderParam.getNotFinish() != null && orderParam.getNotFinish()){
            return findWaitFinish(userId,pageNum,pageSize);
        }

        // 根据关键字搜索订单
        if (orderParam.getKeyword() != null){
            return findByKeyword(userId,pageNum,pageSize,orderParam.getKeyword());
        }
        return findAllOrder(userId,pageNum,pageSize);
    }

    private List<QueryOrderDto> findByKeyword(Long userId, Integer pageNum, Integer pageSize, String keyword) {
        List<ShOrder> orderList = orderMapper.findByKeyword(userId,pageNum,pageSize,keyword);
        List<QueryOrderDto> queryOrderDtos = orderListToDtoList(orderList);
        // 查询对应订单项
        setOrderitemsUnderOrder(queryOrderDtos);

        return queryOrderDtos;
    }

    private List<QueryOrderDto> findAllOrder(Long userId, Integer pageNum, Integer pageSize) {
        PageHelper.startPage(pageNum,pageSize);

        Example example = new Example(ShOrder.class);
        example.orderBy("createTime").desc();

        example.createCriteria()
                .andEqualTo("buyerId",userId)
                .andEqualTo("status",1);
        List<QueryOrderDto> queryOrderDtos = getOrderByExample(example);
        return queryOrderDtos;
    }

    private List<QueryOrderDto> findWaitFinish(Long userId, Integer pageNum, Integer pageSize) {
        PageHelper.startPage(pageNum,pageSize);

        Example example = new Example(ShOrder.class);
        example.createCriteria()
                .andEqualTo("buyerId",userId)
                .andEqualTo("status",1)
                .andIsNull("endTime");

        List<QueryOrderDto> queryOrderDtos = getOrderByExample(example);
        return queryOrderDtos;
    }

    private List<QueryOrderDto> findWaitPayment(Long userId, Integer pageNum, Integer pageSize, OrderParam orderParam) {     //分页
        PageHelper.startPage(pageNum,pageSize);

        Example example = new Example(ShOrder.class);
        example.createCriteria()
                .andEqualTo("buyerId",userId)
                .andEqualTo("status",1)
                .andEqualTo("payStatus",!orderParam.getNotPayment());
        List<QueryOrderDto> queryOrderDtos = getOrderByExample(example);
        return queryOrderDtos;
    }

    private List<QueryOrderDto> getOrderByExample(Example example) {
        // 查询订单
        List<ShOrder> orders = orderMapper.selectByExample(example);
        // 将订单po转换成dto
        List<QueryOrderDto> queryOrderDtos = orderListToDtoList(orders);

        // 查询订单下的订单项
        setOrderitemsUnderOrder(queryOrderDtos);
        return queryOrderDtos;
    }

    // 为QueryOrderItemDto下的订单项成员变量赋值
    private void setOrderitemsUnderOrder(List<QueryOrderDto> queryOrderDtos) {
        queryOrderDtos.forEach(order ->{
            Integer id = order.getOrderId();
            // 利用JSON将po转成dto（前提：dto中的属性都是po中的），其实这个效率不好，但我比较懒
            List<ShOrderItem> orderItems = orderItemMapper.select(ShOrderItem.builder().orderId(id).build());
            List<QueryOrderItemDto> queryOrderItemDtos = QueryOrderItemConvert.INSTANCE.poListToDtoList(orderItems);

            order.setOrderItemDtoList(queryOrderItemDtos);
        });
    }

    // 将订单po集合转换成dto集合
    private List<QueryOrderDto> orderListToDtoList(List<ShOrder> orders) {
        List<QueryOrderDto> queryOrderDtos = new ArrayList<>();
        orders.forEach(order ->{
            QueryOrderDto queryOrderDto = QueryOrderDto.builder()
                    .orderId(order.getId())
                    .sellerId(order.getSellerId())
                    .sellerImg(order.getSellerImg())
                    .sellerName(order.getSellerName())
                    .totalPrice(order.getTotalMoney())
                    .realPayment(order.getRealPayment())
                    .status(-1).build();
            queryOrderDtos.add(queryOrderDto);
        });
        return queryOrderDtos;
    }

    @Override
    public void delete(Long userId, Integer orderId) {
        Example example = new Example(ShOrder.class);
        example.createCriteria()
                .andEqualTo("buyerId", userId)
                .andEqualTo("id", orderId)
                .andEqualTo("status", 1);
        orderMapper.updateByExampleSelective(ShOrder.builder().status(0).updateTime(new Date()).build(), example);
    }

    @Override
    public void update(Long userId, ChangeOrderDto changeOrder) {
        ShOrder order = OrderChangeConvert.INSTANCE.dtoToPo(changeOrder);
        order.setBuyerId(userId);

        // 判断是否改订单是否属于该用户
        ShOrder result = orderMapper.selectByPrimaryKey(order);
        orderMapper.updateByPrimaryKeySelective(order);
    }

    @Override
    @Transactional
    public void add(Long userId, OrderDto orderDto) {
        // 封装订单项信息
        List<OrderItemDto> itemDtoList = orderDto.getOrderItemDtoList();
        List<ShOrderItem> itemList = new ArrayList<>();
        itemDtoList.forEach(item -> {
            ShProduct product = productMapper.selectByPrimaryKey(ShProduct.builder().id(item.getProductId()).build());
            // 少了个商品的卖家信息
            ShOrderItem orderItem = ShOrderItem.builder()
                    .price(product.getPrice())
                    .num(item.getNum())
                    .payMoney(product.getPrice())
                    .totalMoney(product.getPrice()*item.getNum())
                    .productId(product.getId())
                    .productImg(product.getPrimaryPicUrl())
                    .productName(product.getName()).build();
            itemList.add(orderItem);
        });

        // 商品库存递减
        itemDtoList.forEach(item ->{
            int result = productMapper.subStock(item.getProductId(),item.getNum());
            if (result <= 0){
                logger.debug("库存不足{}",item.getProductId());
                System.out.println("库存不足,抛出异常");
//                throw new RuntimeException();
            }
        });

        // 计算这个订单总的价格
        double totalMoney = 0;
        for (ShOrderItem orderItem : itemList) {
            totalMoney += orderItem.getTotalMoney();
        }


        // 封装订单信息
        ShOrder order = ShOrder.builder()
                .buyerId(userId)
                .orderSn(generateOrderSn())
                .sellerId(2L)//先假冒以下
                .receiverName(orderDto.getUsername())
                .receiverPhone(orderDto.getPhone())
                .receiverUniversity(orderDto.getReceiverUniversity())
                .receiverCampus(orderDto.getReceiverCampus())
                .receiverDormitory(orderDto.getReceiverDormitory())
                .receiverRoom(orderDto.getReceiverRoom())
                .receiverComment(orderDto.getReceiverComment())
                .receiverProvince(orderDto.getReceiverProvince())
                .receiverCity(orderDto.getReceiverCity())
                .receiverArea(orderDto.getReceiverArea())
//                .preMoney(orderDto.getPreMoney())
//                .postFee(orderDto.getPostFee()) 都是自己学校的，谈什么邮费
                .realPayment(totalMoney)
                .totalMoney(totalMoney)
                .createTime(new Date())
                .updateTime(new Date())
                .status(1)
                .payStatus(0)
                .build();

        // 订单发送到延迟队列中
        rabbitTemplate.convertAndSend("delayQueue", order, message -> {
            message.getMessageProperties().setExpiration("10000");  //10秒过期
            return message;
        });

        // 将订单插入到数据库
        orderMapper.insert(order);


        // 将订单项插入到数据库（因为订单项需要订单的id，订单的id是插入后才生成的）
        itemList.stream().map(orderItem -> orderItem.setOrderId(order.getId())).forEach(orderItem ->{
            orderItemMapper.insert(orderItem);
        });
        // 等价上面的stream操作
//        for (ShOrderItem orderItem : itemList) {
//            orderItem.setId(order.getId());
//            orderItemMapper.insert(orderItem);
//        }
    }

    @Override
    public void updatePayStatus(String out_trade_no, String time_end) {
        try {
            ShOrder order = orderMapper.selectOne(ShOrder.builder().orderSn(out_trade_no).build());
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
            Date payTime = simpleDateFormat.parse(time_end);
            order.setPayTime(payTime);
            order.setPayStatus(1);  //已支付

            orderMapper.updateByPrimaryKeySelective(order);
        } catch (ParseException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void updatePayStatus(ShOrder order) {
        orderMapper.updateByPrimaryKeySelective(order);
    }

    @Override
    public OrderDetailDto findById(Long userId, Integer orderId) {
        ShOrder order = orderMapper.selectOne(ShOrder.builder().buyerId(userId).id(orderId).build());
        if (order == null) return null; //虽然说正常情况不会null

        List<ShOrderItem> items = orderItemMapper.select(ShOrderItem.builder().orderId(order.getId()).build());
        OrderDetailDto orderDetailDto = OrderDetailConvert.INSTANCE.poToDto(order);
        orderDetailDto.setOrderItemList(items);
        return orderDetailDto;
    }

    /**
     * 生成14位订单编号:8位日期+6位以上自增id
     */
    private String generateOrderSn() {
        StringBuilder sb = new StringBuilder();
        String date = new SimpleDateFormat("yyyyMMdd").format(new Date());
        String key = REDIS_KEY_PREFIX_ORDER_ID + date;
        Long increment =  RedisUtil.increment(key, 1);
        sb.append(date);
        String incrementStr = increment.toString();
        if (incrementStr.length() <= 6) {
            sb.append(String.format("%06d", increment));
        } else {
            sb.append(incrementStr);
        }
        return sb.toString();
    }
}
